package com.wei.web.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.google.gson.*;
import com.wei.annotation.RepeatVerify;
import com.wei.service.wrapper.RedisCacheWrapper;
import com.wei.utils.ApplicationConstants;
import com.wei.utils.CollectionUtils;
import com.wei.utils.ExceptionUtils;
import com.wei.utils.Stringutils;
import com.wei.utils.uuid.UUID;
import com.wei.web.filter.RequestWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Stream;

public class RepeatSubmitHandler extends HandlerInterceptorAdapter {

    @Autowired
    private RedisCacheWrapper redisCacheWrapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!handler.getClass().isAssignableFrom(HandlerMethod.class)) {
            return true;
        }
        HandlerMethod handlerMethod = ((HandlerMethod) handler);
        RepeatVerify repeatVerify = handlerMethod.getMethodAnnotation(RepeatVerify.class);
        if (repeatVerify == null || repeatVerify.primary() == null) {
            for(MethodParameter parameter:handlerMethod.getMethodParameters()){
                if(parameter.hasParameterAnnotation(RepeatVerify.class)){
                    repeatVerify = parameter.getParameterAnnotation(RepeatVerify.class);
                    break;
                }
            }
            if(repeatVerify == null || repeatVerify.primary() == null) {
                return true;
            }
        }
        long timeout = repeatVerify.timeout();
        //判断get post请求
        String key = handlerMethod.getMethod().getName();
        if (ApplicationConstants.GET.equals(request.getMethod())) {//get请求
            for (String param : repeatVerify.primary()) {
                String val = request.getParameter(param);
                if (val == null || val == "") {
                    throw ExceptionUtils.mpe("%s", "非空字段为空!");
                }
                key += "_" + val;
            }

        } else if (ApplicationConstants.POST.equals(request.getMethod())) {//post请求
            RequestWrapper wrapper = new RequestWrapper(request);
            String body = new String(wrapper.getBody(), "UTF-8");
            if (ApplicationConstants.EMPTY.equals(body)) {
                return true;
            }

            //网上的另一种写法 有时间可以试验一下子
//            List<String> params = new ArrayList<>();
//            TreeMap paramTreeMap= new ObjectMapper().readValue(body,TreeMap.class);
//            Stream.of(repeatVerify.primary()).forEach(m->{
//                if(paramTreeMap.containsKey(m)){
//                    params.add( paramTreeMap.get(m).toString());
//                }
//            });
//            if(params.size()>0){
//                key += "_" + Stringutils.join(params,"_");
//            }else{
//                return true;
//            }

            JsonElement jelement = new JsonParser().parse(body);
            if (jelement == null) {
                return true;
            }
            if (jelement.isJsonNull()) {
                return true;
            } else if (jelement.isJsonPrimitive()) {
                JsonPrimitive jprimitive = jelement.getAsJsonPrimitive();
                if (jprimitive.isBoolean()) {
                    key += "_" + jprimitive.getAsBoolean();
                } else if (jprimitive.isNumber()) {
                    key += "_" + jprimitive.getAsNumber();
                } else if (jprimitive.isString()) {
                    key += "_" + jprimitive.getAsString();
                } else {
                    return true;
                }
            } else {
                key = JObject(jelement, key, repeatVerify.primary());
            }
        }
        String uuid = UUID.randomUUID().toString();
        if (!handlerMethod.getMethod().getName().equals(key)
                && !redisCacheWrapper.tryLock(key, uuid, (int) (timeout / 1000))) {
            throw ExceptionUtils.mpe("%s", "重复请求!");
        } else {
            return true;
        }
    }


    public String JObject(JsonElement jelement, String key, String[] strs) {
        if (jelement.isJsonObject()) {
            JsonObject jobject = jelement.getAsJsonObject();
            for (Map.Entry<String, JsonElement> entry : jobject.entrySet()) {
                if (Stream.of(strs).anyMatch(m -> m.equals(entry.getKey()))) {
                    key += "_" + entry.getValue();
                }
            }
        } else if (jelement.isJsonArray()) {
            JsonArray jarray = jelement.getAsJsonArray();
            for (int index = 0; index < jarray.size(); index++) {
                key = JObject(jarray.get(index), key, strs);
            }
        }
        return key;
    }
}
